package com.yjzx.util.common.util.encrypt;

import com.yjzx.util.common.execption.TokenException;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yjzx
 * @date 2023/11/06
 * @description JWT工具类,生成的token使用aes再次加密
 */
public class JwtUtil {
    /**
     * 过去时长
     */
    public static final String EXD = "exd";
    /**
     * 过期时间
     */
    public static final String EXP = "exp";
    /**
     * 签发时间
     */
    public static final String IAT = "iat";
    /**
     * 用户名
     */
    public static final String SUB = "sub";
    /**
     * token
     */
    public static final String TOKEN = "token";

    /**
     * token加密 key（jwt数据明文）
     */
    public static final String ENCRYPT_KEY = "UwkJLE9cuAJAJvV0";
    /**
     * token加密iv
     */
    public static final String IV_BYTE = "FduD5KUWIVK3C0Xh";




    /**
     * 生成token
     * @param operatorId id
     * @param expireTime 有效期
     * @return
     */
    public static Map<String, Object> getAccessToken(String operatorId, Long expireTime) {
        Map<String, Object> map = toMap(operatorId, expireTime);
        String token = generateToken(map);
        token = AES.encrypt(token,ENCRYPT_KEY,IV_BYTE);
        map.put(TOKEN, token);
        return map;
    }

    /**
     * 校验token 并提取对应的
     *
     * @param request 请求
     * @return {@link String}
     * 如果校验成功返回用户
     */
    public static String validateAccessToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.isEmpty(bearerToken)) {
            throw new TokenException("token不存在!");
        }
        if (bearerToken.length() < TOKEN_HEADER_LENGTH) {
            throw new TokenException("token类型不正确!");
        }
        String token = bearerToken.substring(TOKEN_HEADER_LENGTH);
        if (StringUtils.isEmpty(token)) {
            throw new TokenException("token不能为空!");
        }

        return JwtUtil.validateToken(token);
    }


    static String validateToken(String token) {
        try {
            token = AES.decrypt(token,ENCRYPT_KEY,IV_BYTE);
            Map<String, Object> body = Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
            return (String) body.get(SUB);
        } catch (ExpiredJwtException e) {
            throw new TokenException("token已经超时!");
        } catch (Exception e) {
            throw new TokenException("非法token!");
        }
    }


    /**
     * 久融内部key(十分重要,不可以泄漏)
     */
    private static final String SECRET = "j.r.x.n.y:2023";

    /**
     * 认证的key需要剔除头部border {@value}
     */
    private static final int TOKEN_HEADER_LENGTH = 7;

    /**
     * 根据用户的信息生成对应的token
     *
     * @param map 用户信息
     * @return token
     */
    private static String generateToken(Map<String, Object> map) {
        //返回生成token信息
        return Jwts.builder()
                .setClaims(map)
                .setExpiration((Date) map.get(EXP))
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    private static Map<String, Object> toMap(String operatorId, Long expireTime) {
        Map<String, Object> map = new HashMap<>(4);
        map.put(SUB, operatorId);
        long timeMillis = System.currentTimeMillis();
        map.put(IAT, new Date(timeMillis));
        map.put(EXP, new Date(timeMillis + expireTime * 1000L));
        map.put(EXD, expireTime.toString());
        return map;
    }


}
